/**
 * @file
 * Worker thread header file.
 *
 * Kisa provides spell checking as you type and displays the result in a small
 * window on your Desktop.
 *
 * Copyright (c) 2009 by Pete Black <theblackpeter@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * @author Pete Black <theblackpeter@gmail.com>
 */
#ifndef KISATHREAD_H
#define KISATHREAD_H

#include <QThread>
#include <QtDebug>

#include "kisalib.h"

/**
 * @class KisaThread
 * The KisaThread class provides a worker thread that does all the event
 * handling. It gives a separate level of control within the application by
 * containing these operations in a separate thread. Whenever a new event is
 * available on the X server's event queue, it's sent back to the main
 * application event loop for further processing.
 *
 * The thread also keeps track of the visibility state of the main widget
 * window.
 *
 * @note Don't call the run() method directly, uses startToggle() instead.
 * To stop the thread call stop().
 *
 * @author Pete Black <theblackpeter@gmail.com>
 * @see Kisa
 */
class KisaThread : public QThread {
  Q_OBJECT

  public:
  /**
   * Creates a KisaThread.
   *
   * @param parent pointer to parent object
   */
  KisaThread(QObject* parent = NULL);

  /**
   * Destructor.
   */
  virtual ~KisaThread();

  /**
   * Sets the member variable that controls the termination of the thread run
   * function. Whenever this variable is @c true the thread will terminate
   * its execution. Otherwise, the tread will continue as usual
   *
   * @param done change the done variable to this
   * @see isDone
   */
  void setDone(const bool& done) { isDone = done; }

  protected:
  /**
   * All events are processed here. Returning from this method will end the
   * execution of the thread. This is simply done by setting the #isDone
   * variable to @c true.
   *
   * @see setDone()
   */
  void run();

  public slots:
  /**
   * Calls the corresponding library function KisaLib#replaceInClient() with
   * the window id from the last originating keypress event. This will replace
   * the misspelled word @p misspelled with the suggested, @p suggestion.
   *
   * @warning Be careful when doing this, as we can't be sure that we are
   * replacing the right word in the right window. There is no way of knowing
   * what exactly is going on in any arbitrary window on the desktop.
   * Unexpected behavior may occur.
   *
   * @param misspelled the word to replace, that is the misspelled word
   * @param suggestion the word new replacement word, that is the suggestion
   * selected by the user
   * @param residual contains everything else that was inputed after the spell
   * check was triggered, for example punctuation characters
   * @see KisaLib::replaceInClient
   */
  void replaceInClient(const QString& misspelled,
                       const QString& suggestion,
                       const QString& residual = QString());

  /**
   * Starts the thread if it's not running or stops it if it is.
   */
  void startToggle();

  /**
   * Stops the thread execution safely. Brakes any blocking X11 event call by
   * sending a bogus (fake) event to the X server originating from the root
   * window (desktop window).
   *
   * @return @c true if the thread was successfully stopped, @c false
   * otherwise
   */
  bool stop();

  signals:
  /**
   * This signal is emitted whenever a new event containing a keypress
   * character is made available from X server.
   *
   * @param character
   */
  void gotNewCharacter(const QChar& character);

  /**
   * This signal is emitted whenever the visibility state of the main window
   * widget is changed.
   *
   * The possible X11 visibility states are:
   *  @li VisibilityUnobscured
   *  @li VisibilityPartiallyObscured
   *  @li VisibilityFullyObscured
   */
  void visibilityStateChange(const int&);

  private:
  /**
   * This flag determines when to stop the thread execution. When set to
   * @c true the thread loop run() will exit, otherwise it will continue.
   *
   * @see setDone()
   * @see run()
   */
  volatile bool isDone;

  /**
   * Pointer to the library object.
   */
  KisaLib* kisaLib;

  /**
   * The last keypress event is stored here. Used bu replaceInClient() when
   * replacing words in the client application window.
   *
   * @see replaceInClient()
   */
  KisaEvent lastKeyEvent;

};

#endif
